home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 1 / PC Actual CD 01.iso / share / dos / demos / planets / source.lzh / PLANETS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-02  |  18.4 KB  |  682 lines

  1.  
  2. /*
  3.  *  PLANETS.C
  4.  *
  5.  *  (Simon Hern, 1994)
  6.  *
  7.  *  Animation of rotating planets bouncing up and down stupidly
  8.  *
  9.  *  Command-line options: /s to switch off end message, /t<time> to set a
  10.  *   time limit, /f<path> to specify location of data files, and /p<n> to
  11.  *   select the number of planets (1, 2 or 3, as memory allows)
  12.  *
  13.  *  Uses XLib06 for page flipping in Mode X
  14.  *  Additional assembly language routine in GUSHCODE.ASM
  15.  *  Some extra definitions in header file PLANET.H
  16.  *
  17.  *  Associated data files: GUSH1.DAT, GUSH2.DAT, GUSH3.DAT
  18.  *                         XION1.DAT, XION2.DAT, XION3.DAT
  19.  *  (These files could've been made smaller, but that would've slowed the
  20.  *   demo down on loading as it expanded the data, so I decided against it)
  21.  *
  22.  *
  23.  *  As far as I can tell this program works perfectly (Ha!)
  24.  *  But obvious sources of potential problems are:
  25.  *    (i)  The heavy duty maths involved with the Gush and the Xion
  26.  *          - errors here are nearly impossible to catch
  27.  *    (ii) The large arrays
  28.  *          - using arrays exactly 64k long was a bad idea
  29.  *
  30.  */
  31.  
  32.  
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <time.h>
  37. #include <conio.h>
  38. #include <alloc.h>
  39. #include <string.h>
  40. #include <math.h>
  41.  
  42. /* XLib v06 */
  43. #include <xlib.h>
  44. #include <xrect.h>
  45. #include <xpal.h>
  46. #include <xfileio.h>
  47. #include <xvsync.h>
  48.  
  49. /* Local definitions (notably RHO: the surface resolution) */
  50. #include "planet.h"
  51.  
  52.  
  53.  
  54. /* Planet drawing routine (from GUSHCODE.ASM) */
  55. extern void display_gush(int x, int y, int rot, char far * gu, char far * xi);
  56.  
  57. /* XLib variable: start of useful video memory */
  58. extern WORD HiddenPageOffs;
  59.  
  60.  
  61.  
  62. /* Screen parameters (Mode X) */
  63. #define SCR_WIDTH 320
  64. #define SCR_HEIGHT 240
  65.  
  66. /* Names of additional files */
  67. #define GUSH_FILE "GUSH"
  68. #define XION_FILE "XION"
  69. #define FILE_EXT ".DAT"
  70.  
  71. /* Default running time (secs), if set to run for a limited time */
  72. #define DEFAULT_TIME 120
  73.  
  74. /* Maximum number of planets that can be thrown around */
  75. #define MAX_PLANETS 3
  76.  
  77. /* Total number of colours used for planets */
  78. #define COLOURS 2*MAX_PLANETS
  79. /* Number of shades of each colour in palette */
  80. #define SHADES 40
  81.  
  82. /* Number of background stars */
  83. #define STARS 200
  84. /* Number of palette colours used for stars */
  85. #define STAR_COLS 10
  86. /* Start position in palette of star colours */
  87. #define STAR_COL_START COLOURS*SHADES+1
  88.  
  89.  
  90. /* Check we've not assigned more than 256 colours */
  91. #if COLOURS*SHADES + STAR_COLS > 255
  92. #error Too many colours used in 256-colour mode
  93. #endif
  94.  
  95.  
  96.  
  97. /* Structure containing data for one planet */
  98. typedef struct {
  99.     char far * gush;      /* Pointer to data&code for drawing the planet */
  100.     char huge * xion;     /* Pointer to planet surface data */
  101.     int radius;           /* Radius of planet (in pixels) */
  102.     int xpos, ypos;       /* Coordinates (across, down) of top-left */
  103.                              /* 'corner' of planet on screen */
  104.     int rot;              /* Degree of rotation of planet */
  105.     int x2, y2, x3, y3;   /* Remembered coordinates in previous frames */
  106.     int dx, dr;           /* Rates of change of 'xpos' and 'rot' */
  107.     float acc;            /* Constant determining 'bounce' parabola */
  108.     int tparm, trange;    /* Time parameter over parabola, and its extremes */
  109.     int margin;           /* Gap between top of screen and height of bounce */
  110. } PlanetStruc;
  111.  
  112.  
  113.  
  114. /* Structure for position and colour of a star */
  115. typedef struct {
  116.     unsigned int offset;   /* Star position, offset into video page */
  117.     unsigned char plane;   /* Star position, ModeX video plane */
  118.     unsigned char colour;  /* Colour of star */
  119. } StarStruc;
  120.  
  121.  
  122.  
  123. /* Exit functions */
  124. void terminate();
  125. int controlbreak();
  126.  
  127. /* All-gone-horribly-wrong-please-let-me-out-of-here function */
  128. void error(char * m1, char * m2, char * m3);
  129.  
  130. /* Credits and stuff */
  131. void end_message();
  132.  
  133. /* Generate a random list of numbers */
  134. void shuffle(int cards[], int num);
  135.  
  136. /* Load data into far memory */
  137. int far_load(char * fname, char far * dest, unsigned len);
  138.  
  139. /* Create stars, display stars */
  140. void make_stars();
  141. void plot_stars();
  142.  
  143. /* Generate palette data for planets, for stars, and for everything */
  144. void planet_cols();
  145. void star_cols();
  146. void set_cols();
  147.  
  148. /* Do things with planets, all of them */
  149. void make_planets();
  150. void swap_planets();
  151. void move_planets();
  152. void display_planets();
  153. void erase_planets();
  154. void kill_planets();
  155.  
  156. /* Do things with planets, one at a time */
  157. void init_planet(PlanetStruc *pp, char *gfile, char *xfile, unsigned char d);
  158. void kill_planet(PlanetStruc * pp);
  159. void move_planet(PlanetStruc * pp);
  160. void display_planet(PlanetStruc * pp);
  161. void erase_planet(PlanetStruc * pp);
  162.  
  163.  
  164.  
  165. /* Colours to choose from when decorating the planets */
  166. int colours[COLOURS][3] = {
  167.     63, 40, 0,    /* Yellow */
  168.     63, 0, 40,    /* Pink */
  169.     63, 0, 5,     /* Red */
  170.     0, 63, 0,     /* Green */
  171.     10, 10, 63,   /* Blue */
  172.     0, 63, 40     /* Cyan */
  173. };
  174.  
  175.  
  176. /* Palette of 256 colours */
  177.   /* 0 : background (black) */
  178.   /* 1 -- COLOURS*SHADES : colours for planets (blocks of length SHADES) */
  179.   /* STAR_COL_START -- STAR_COL_START+STAR_COLS-1 : colours for stars */
  180. char far palette[256][3];
  181.  
  182.  
  183. /* Display message (or not) at end of demo */
  184. int message = 1;
  185.  
  186. /* Directory in which to find data files */
  187. char fpath[80] = "";  /* Current directory by default */
  188.  
  189.  
  190. /* Array of stars */
  191. StarStruc stars[STARS];
  192.  
  193.  
  194. /* Array of planets */
  195. PlanetStruc planet[MAX_PLANETS];
  196.  
  197. /* Planets listed in the order they appear on screen */
  198. int order[MAX_PLANETS];
  199.  
  200. /* The number of planets actually used */
  201. int planets;
  202.  
  203.  
  204.  
  205. /* CODE STARTS HERE ! */
  206.  
  207. int main(int argc, char *argv[]) {
  208.  
  209.     int timer=0, twait, time_up=0;
  210.     time_t tstart=time(NULL);
  211.     int s;
  212.  
  213.     randomize();
  214.  
  215.   /* As many planets as will fit in memory */
  216.     planets = farcoreleft() / (65535L + 4*(long)RHO*RHO);
  217.     if ( planets > MAX_PLANETS ) planets = MAX_PLANETS;
  218.     if ( planets <= 0 ) {
  219.         error("It might help if there was a little free memory", "", "");
  220.     }
  221.  
  222.   /* Command-line options */
  223.     for ( s = 1 ; s < argc ; s++ ) {
  224.         if ( argv[s][0] != '/' && argv[s][0] != '-' ) {
  225.             error(argv[s], "? That\'s no way to select a program option!", "");
  226.         }
  227.         if ( argv[s][1] == 's' || argv[s][1] == 'S' ) {
  228.           /* Switch off end message */
  229.             message = 0;
  230.         } else if ( argv[s][1] == 't' || argv[s][1] == 'T' ) {
  231.           /* Run demo for fixed length of time */
  232.             timer = 1;
  233.             twait = atoi(argv[s]+2);
  234.             if ( twait <= 0 ) twait = DEFAULT_TIME;
  235.         } else if ( argv[s][1] == 'f' || argv[s][1] == 'F' ) {
  236.           /* Set file search path */
  237.             strcpy(fpath, argv[s]+2);
  238.             if ( fpath[0] != '\0' && fpath[strlen(fpath)-1] != '\\'
  239.                     && fpath[strlen(fpath)-1] != ':' ) {
  240.                 fpath[strlen(fpath)+1] = '\0';
  241.                 fpath[strlen(fpath)] = '\\';
  242.             }
  243.         } else if ( argv[s][1] == 'p' || argv[s][1] == 'P' ) {
  244.           /* Select number of planets to bounce */
  245.             planets = argv[s][2] - '0';
  246.             if ( planets<1 || planets>MAX_PLANETS || strlen(argv[s])>3 ) {
  247.                 error("How many planets?!", "", "");
  248.             }
  249.         } else error("What\'s ", argv[s], " supposed to mean then?");
  250.     }
  251.  
  252.   /* Load and arrange data */
  253.     make_planets();
  254.     make_stars();
  255.  
  256.   /* XLib vsynced trip(p)le buffering (good stuff!) */
  257.   /* Screen updates 30 times a second (sets a maximum animation rate) */
  258.     x_set_mode(X_MODE_320x240, SCR_WIDTH);
  259.     x_install_vsync_handler(2);
  260.     x_set_tripplebuffer(SCR_HEIGHT);
  261.   /* Last one out, please turn off Mode X */
  262.     atexit(terminate);
  263.     ctrlbrk(controlbreak);
  264.  
  265.   /* Palette */
  266.     set_cols();
  267.  
  268.   /* Now, until a key is pressed or time runs out... */
  269.     while ( !kbhit() && !time_up ) {
  270.  
  271.         move_planets();     /* Reposition planets for next frame */
  272.         plot_stars();       /* Redraw the background stars */
  273.         display_planets();  /* Draw the planets */
  274.         x_page_flip(0,0);   /* Display this frame */
  275.         erase_planets();    /* Clean the planet remains from the old frame */
  276.         swap_planets();     /* Change the order of the planets occasionally */
  277.  
  278.         if ( time(NULL) > tstart + twait ) time_up = 1;
  279.     }
  280.  
  281.   /* Tidy up and go home */
  282.     while ( kbhit() ) getch();
  283.     kill_planets();
  284.     if ( timer && !time_up ) return 1;
  285.     return 0;
  286. }
  287.  
  288.  
  289.  
  290. /* Exit function (shut off graphics mode before terminating) */
  291.  
  292. void terminate() {
  293.     x_remove_vsync_handler();
  294.     x_text_mode();
  295.     if ( message ) end_message();
  296. }
  297.  
  298.  
  299.  
  300. /* Control-Break handler */
  301.  
  302. int controlbreak() {
  303.     terminate();
  304.     return 0;
  305. }
  306.  
  307.  
  308.  
  309. /* Display error message (in up to three bits), then die */
  310.  
  311. void error(char * m1, char * m2, char * m3) {
  312.     end_message();
  313.     printf("\nSimon says: %s%s%s\n\n", m1, m2, m3);
  314.     exit(-1);
  315. }
  316.  
  317.  
  318.  
  319. /* Display the end message */
  320.  
  321. void end_message() {
  322.     printf("\n"
  323.            "  BOUNCING PLANETS DEMO\n"
  324.            "  Simon Hern (22 Harrington Drive, Bedford, MK41 8DB, England)\n"
  325.            "  April 1994\n"
  326.            "\n"
  327.            "  Command-line options:\n"
  328.            "     /s       : suppress this end message\n"
  329.            "     /t<time> : stop demo after <time> seconds\n"
  330.            "     /p<n>    : bounce <n> planets (up to 3)\n"
  331.            "     /f<path> : look for data files in <path> directory\n"
  332.            "\n");
  333. }
  334.  
  335.  
  336.  
  337. /* Places numbers 0 to ('num'-1) into 'cards' array in a random order */
  338. /* Used for deciding which planet uses which data */
  339.  
  340. void shuffle(int cards[], int num) {
  341.     int i, r;
  342.     for ( i=0 ; i<num ; i++ ) cards[i] = -1;
  343.     for ( i=0 ; i<num ; i++ ) {
  344.         do { r = random(num); }
  345.         while ( cards[r] != -1 );
  346.         cards[r] = i;
  347.     }
  348. }
  349.  
  350.  
  351.  
  352. /* Function to load data to 'far' array (up to 65535 bytes) */
  353. /* Uses XLib file functions (since they work with 'far') */
  354.  
  355. int far_load(char * fname, char far * dest, unsigned len) {
  356.     int fin;
  357.     unsigned l;
  358.  
  359.     fin = f_open(fname, F_RDONLY);
  360.     if ( fin == FILE_ERR ) return 0;
  361.  
  362.     l = f_readfar(fin, dest, len);
  363.  
  364.     f_close(fin);
  365.     return l;
  366. }
  367.  
  368.  
  369.  
  370. /* Fill up the array of stars; random positions, random colours */
  371.  
  372. void make_stars() {
  373.     int s;
  374.     for ( s=0 ; s<STARS ; s++ ) {
  375.         stars[s].offset = random(SCR_WIDTH*(SCR_HEIGHT/4));
  376.         stars[s].plane = 1 << random(4);
  377.         stars[s].colour = STAR_COL_START + random(STAR_COLS);
  378.     }
  379. }
  380.  
  381.  
  382.  
  383. /* Plot all the stars onto the 'hidden' video page */
  384.  
  385. void plot_stars() {
  386.     int s;
  387.     for ( s=0 ; s<STARS ; s++ ) {
  388.         outport(0x03c4, (256*(int)stars[s].plane)+2);
  389.         pokeb(0xa000, HiddenPageOffs + stars[s].offset, stars[s].colour);
  390.     }
  391. }
  392.  
  393.  
  394.  
  395. /* Choose random colours for the planets and fill the palette */
  396.  
  397. void planet_cols() {
  398.     int i,j;
  399.     float s;
  400.     int cards[COLOURS];
  401.  
  402.     shuffle(cards, COLOURS);
  403.     for ( i = 0 ; i < SHADES ; i++ ) {
  404.         s = i/((float)SHADES-1);
  405.  
  406.         for ( j = 0 ; j < COLOURS ; j += 2 ) {
  407.             palette[i + j*SHADES + 1][0] = (1-s) * colours[cards[j]][0];
  408.             palette[i + j*SHADES + 1][1] = (1-s) * colours[cards[j]][1];
  409.             palette[i + j*SHADES + 1][2] = (1-s) * colours[cards[j]][2];
  410.  
  411.             palette[i + (j+1)*SHADES + 1][0] = s * colours[cards[j+1]][0];
  412.             palette[i + (j+1)*SHADES + 1][1] = s * colours[cards[j+1]][1];
  413.             palette[i + (j+1)*SHADES + 1][2] = s * colours[cards[j+1]][2];
  414.         }
  415.     }
  416. }
  417.  
  418.  
  419.  
  420. /* Set up the star colours in the palette (shades of grey) */
  421.  
  422. void star_cols() {
  423.     int c;
  424.     for ( c = 0 ; c < STAR_COLS ; c++ ) {
  425.         palette[STAR_COL_START + c][0] = palette[STAR_COL_START + c][1]
  426.             = palette[STAR_COL_START + c][2] = 63.0 * (c+1) / (float)STAR_COLS;
  427.     }
  428. }
  429.  
  430.  
  431.  
  432. /* Generate palette data for background, planets and stars */
  433.  
  434. void set_cols() {
  435.     palette[0][0] = palette[0][1] = palette[0][2] = 0;
  436.     planet_cols();
  437.     star_cols();
  438.     x_put_pal_raw((char far *)palette, 256, 0);
  439. }
  440.  
  441.  
  442.  
  443. /* Initialise all the planets (includes loading in data) */
  444.  
  445. void make_planets() {
  446.     int i;
  447.     int gcards[MAX_PLANETS];
  448.     int xcards[MAX_PLANETS];
  449.     char gfile[80];
  450.     char xfile[80];
  451.  
  452.   /* Jack Names the Planets */
  453.     shuffle(gcards, MAX_PLANETS);
  454.     shuffle(xcards, MAX_PLANETS);
  455.   /* Load in data for the active planets in a random order */
  456.     for ( i = 0 ; i < planets ; i++ ) {
  457.         strcpy(gfile, fpath);
  458.         strcpy(xfile, fpath);
  459.         strcat(gfile, GUSH_FILE);
  460.         strcat(xfile, XION_FILE);
  461.         gfile[strlen(gfile)+1] ='\0';
  462.         gfile[strlen(gfile)] ='1' + gcards[i];
  463.         xfile[strlen(xfile)+1] ='\0';
  464.         xfile[strlen(xfile)] ='1' + xcards[i];
  465.         strcat(gfile, FILE_EXT);
  466.         strcat(xfile, FILE_EXT);
  467.       /* Files are: GUSH1.DAT, XION1.DAT, GUSH2.DAT, XION2.DAT, etc */
  468.         init_planet(&planet[i], gfile, xfile, i*2*SHADES);
  469.     }
  470.  
  471.   /* Random starting x coordinate */
  472.     for ( i = 0 ; i < planets ; i++ ) {
  473.         planet[i].xpos = random(SCR_WIDTH - 2*planet[i].radius);
  474.     }
  475.  
  476.  
  477.   /* Some constants, different for each planet (3 planets accounted for) */
  478.     planet[0].dx = 3;
  479.     planet[0].dr = -2;
  480.     planet[0].acc = 0.2;
  481.     planet[0].margin = 0;
  482.  
  483.     planet[1].dx = -2;
  484.     planet[1].dr = -3;
  485.     planet[1].acc = 0.35;
  486.     planet[1].margin = 10;
  487.  
  488.     planet[2].dx = -3;
  489.     planet[2].dr = 4;
  490.     planet[2].acc = 0.3;
  491.     planet[2].margin = 25;
  492.  
  493.   /* Parameter range and random starting time */
  494.     for ( i = 0 ; i < planets ; i++ ) {
  495.         planet[i].trange = sqrt(
  496.                   (SCR_HEIGHT - planet[i].margin - 2*planet[i].radius - 1)
  497.                            / planet[i].acc );
  498.         planet[i].tparm = planet[i].trange * (random(199)-99) / 100.0;
  499.     }
  500.  
  501.   /* The planets in order */
  502.     for ( i = 0 ; i < planets ; i++ ) order[i] = i;
  503. }
  504.  
  505.  
  506.  
  507. /* From time to time, switch over the orderings of two planets */
  508. /* Planets must not be overlapping at the time */
  509.  
  510. void swap_planets() {
  511.     static int swap = 50;
  512.     int x, s;
  513.  
  514.     if ( planets <= 1 ) return;
  515.  
  516.     if ( --swap == 0 ) {
  517.         swap= 10 + random(40);
  518.         x = random(planets-1);
  519.         if ( ( planet[order[x]].xpos - planet[order[x+1]].xpos
  520.                         > 2*planet[order[x+1]].radius )
  521.                 || ( planet[order[x+1]].xpos - planet[order[x]].xpos
  522.                         > 2*planet[order[x]].radius ) ) {
  523.             s = order[x];
  524.             order[x] = order[x+1];
  525.             order[x+1] = s;
  526.         }
  527.     }
  528. }
  529.  
  530.  
  531.  
  532. /* Move all of the planets */
  533.  
  534. void move_planets() {
  535.     int x;
  536.     for ( x = 0 ; x < planets ; x++ ) move_planet(&planet[order[x]]);
  537. }
  538.  
  539.  
  540.  
  541. /* Display all of the planets */
  542.  
  543. void display_planets() {
  544.     int x;
  545.     for ( x = 0 ; x < planets ; x++ ) display_planet(&planet[order[x]]);
  546. }
  547.  
  548.  
  549.  
  550. /* Erase all of the planets */
  551.  
  552. void erase_planets() {
  553.     int x;
  554.     for ( x = 0 ; x < planets ; x++ ) erase_planet(&planet[order[x]]);
  555. }
  556.  
  557.  
  558.  
  559. /* Kill all of the planets */
  560.  
  561. void kill_planets() {
  562.     int x;
  563.     for ( x = 0 ; x < planets ; x++ ) kill_planet(&planet[order[x]]);
  564. }
  565.  
  566.  
  567.  
  568. /* Initialise a planet, given a gush file name and a xion file name */
  569. /* Add 'd' to every point in xion (different colours for different planets) */
  570.  
  571. void init_planet(PlanetStruc *pp, char *gfile, char *xfile, unsigned char d) {
  572.     int x,y;
  573.     char far * dest;
  574.     char far * source;
  575.  
  576.   /* Allocate memory */
  577.     pp->gush = (char far *)farmalloc(65535L);
  578.     if ( pp->gush == NULL ) {
  579.         error("Too much *gush*, too little memory", "", "");
  580.     }
  581.     pp->xion = (char huge *)farmalloc(4*(long)RHO*RHO);
  582.     if ( pp->xion == NULL ) {
  583.         error("Too much *xion*, too little memory", "", "");
  584.     }
  585.  
  586.   /* Load files */
  587.     if ( ! far_load(gfile, pp->gush, 65535) ) {
  588.         error("What have you done with my ", gfile, " file?");
  589.     }
  590.     if ( ! far_load(xfile, (char far *)pp->xion, 2*RHO*RHO) ) {
  591.         error("What have you done with my ", xfile, " file?");
  592.     }
  593.  
  594.   /* Expand Complexion */
  595.   /* (Each line repeated, 'd' added on at each point) */
  596.     source = ((char far *)(pp->xion)) + 2*RHO*RHO - 1;
  597.     dest = ((char far *)(pp->xion)) + 4*RHO*RHO - 1;
  598.     for ( y = RHO ; y > 0 ; y-- ) {
  599.         for ( x = 2*RHO ; x > 0 ; x-- ) {
  600.             *dest = *(dest-2*RHO) = *source + d;
  601.             source--;
  602.             dest--;
  603.         }
  604.         dest -= 2*RHO;
  605.     }
  606.  
  607.   /* Initialise a variable */
  608.     pp->radius = pp->gush[0];
  609.  
  610.   /* Blank some other variables */
  611.     pp->xpos = pp->ypos = pp->x2 = pp->y2 = pp->x3 = pp->y3 = 0;
  612.     pp->rot = pp->dr = pp->dx = pp->tparm = pp->margin = 0;
  613.     pp->trange = 10;
  614.     pp->acc = 1;
  615. }
  616.  
  617.  
  618.  
  619. /* Deallocate planet's memory */
  620.  
  621. void kill_planet(PlanetStruc * pp) {
  622.     farfree((void far *)pp->gush);
  623.     farfree((void far *)pp->xion);
  624. }
  625.  
  626.  
  627.  
  628. /* Move planet: constant x velocity (with bounce at ends), */
  629. /*  parabola in y (based on tparm), constant rotational velocity */
  630.  
  631. void move_planet(PlanetStruc * pp) {
  632.  
  633.     pp->x3 = pp->x2;
  634.     pp->y3 = pp->y2;
  635.     pp->x2 = pp->xpos;
  636.     pp->y2 = pp->ypos;
  637.  
  638.     pp->xpos += pp->dx;
  639.     if ( (pp->xpos) >= SCR_WIDTH - 2*(pp->radius) ) {
  640.         pp->xpos = SCR_WIDTH - 2*(pp->radius) - 1;
  641.         pp->dx = -(pp->dx);
  642.     }
  643.     if ( (pp->xpos) < 0 ) {
  644.         pp->xpos = 0;
  645.         pp->dx = -(pp->dx);
  646.     }
  647.  
  648.     pp->ypos = pp->margin + (pp->acc) * (pp->tparm) * (pp->tparm);
  649.     if ( ++(pp->tparm) > (pp->trange) ) {
  650.         pp->tparm = -(pp->tparm) + 1;
  651.     }
  652.  
  653.     pp->rot += pp->dr;
  654.     while ( pp->rot < 0 ) pp->rot += 2*RHO;
  655.     while ( pp->rot >= 2*RHO ) pp->rot -= 2*RHO;
  656. }
  657.  
  658.  
  659.  
  660. /* Draw the planet (checking position is within bounds) */
  661.  
  662. void display_planet(PlanetStruc * pp) {
  663.     if ( pp->xpos < 0 || pp->xpos >= SCR_WIDTH-2*(pp->radius) ) pp->xpos = 0;
  664.     if ( pp->ypos < 0 || pp->ypos >= SCR_HEIGHT-2*(pp->radius) ) pp->ypos = 0;
  665.     if ( pp->rot < 0 || pp->rot >= 2*RHO ) pp->rot = 0;
  666.  
  667.     display_gush(pp->xpos, pp->ypos, pp->rot,
  668.                  (char far *)pp->gush, (char far *)pp->xion);
  669. }
  670.  
  671.  
  672.  
  673. /* Draw black rectangle over old planet position */
  674.  
  675. void erase_planet(PlanetStruc * pp) {
  676.     x_rect_fill(pp->x3, pp->y3,
  677.                 (pp->x3) + 2*(pp->radius), (pp->y3) + 2*(pp->radius),
  678.                 HiddenPageOffs, 0);
  679. }
  680.  
  681.  
  682.